﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using IdCardReaderHelper.Models;
using Image = System.Drawing.Image;

namespace IdCardReaderHelper.Common
{
    public class IdCardReader
    {
        #region 函数

        /************************端口类API *************************/
        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetMaxRFByte", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetMaxRFByte(int iPort, byte ucByte, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_GetCOMBaud", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_GetCOMBaud(int iPort, ref uint puiBaudRate);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetCOMBaud", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetCOMBaud(int iPort, uint uiCurrBaud, uint uiSetBaud);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_OpenPort", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_OpenPort(int iPort);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ClosePort", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ClosePort(int iPort);

        /**************************SAM类函数 **************************/
        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ResetSAM", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ResetSAM(int iPort, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_GetSAMStatus", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_GetSAMStatus(int iPort, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_GetSAMID", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_GetSAMID(int iPort, ref byte pucSAMID, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_GetSAMIDToStr", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_GetSAMIDToStr(int iPort, ref byte pcSAMID, int iIfOpen);

        /*************************身份证卡类函数 ***************************/
        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_StartFindIDCard", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_StartFindIDCard(int iPort, ref byte pucIIN, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SelectIDCard", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SelectIDCard(int iPort, ref byte pucSN, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadBaseMsg", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ReadBaseMsg(int iPort, IntPtr pucCHMsg, ref uint puiCHMsgLen, IntPtr pucPHMsg,
            ref uint puiPHMsgLen, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadIINSNDN", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ReadIINSNDN(int iPort, ref byte pucIINSNDN, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadBaseMsgToFile", CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern int Syn_ReadBaseMsgToFile(int iPort, ref byte pcCHMsgFileName, ref uint puiCHMsgFileLen,
            ref byte pcPHMsgFileName, ref uint puiPHMsgFileLen, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadIINSNDNToASCII", CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern int Syn_ReadIINSNDNToASCII(int iPort, ref byte pucIINSNDN, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadNewAppMsg", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ReadNewAppMsg(int iPort, ref byte pucAppMsg, ref uint puiAppMsgLen, int iIfOpen);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_GetBmp", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_GetBmp(string Wlt_File, int iPort);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_ReadMsg", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, ref IDCardData pIDCardData);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_FindReader", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_FindReader();

        /***********************设置附加功能函数 ************************/
        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetPhotoPath", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetPhotoPath(int iOption, ref byte cPhotoPath);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetPhotoType", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetPhotoType(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetPhotoName", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetPhotoName(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetSexType", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetSexType(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetNationType", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetNationType(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetBornType", CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern int Syn_SetBornType(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetUserLifeBType", CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern int Syn_SetUserLifeBType(int iType);

        [DllImport("idCardDll\\SynIDCardAPI.dll", EntryPoint = "Syn_SetUserLifeEType", CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern int Syn_SetUserLifeEType(int iType, int iOption);

        [DllImport("idCardDll\\WltRS.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        static extern int GetBmp(string pucPHMsg, int intf);

        #endregion

        private static string _imageDirPath = "CardImg";

        public static bool CheckCardSuccess()
        {
           var i = Syn_FindReader();
            return i > 1000;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCardData"></param>
        /// <returns>
        ///0：读取成功
        ///1：找不到身份证
        ///2：找不到读卡器
        ///3:读取失败
        /// </returns>
        public static int Read(ref IDCardData idCardData)
        {
            if (!Directory.Exists(_imageDirPath))
            {
                Directory.CreateDirectory(_imageDirPath);
            }
            int status = 1;//默认为找不到身份证
            try
            {
                //先查找读卡器
                int i, nRet;
                i = Syn_FindReader();
                //只支持usb
                if (i > 1000)
                {
                    var nPort = i;
                    if (Syn_OpenPort(nPort) == 0)
                    {
                        Thread.Sleep(5);
                        if (Syn_SetMaxRFByte(nPort, 80, 0) == 0)
                        {
                            Thread.Sleep(5);
                            byte[] pucIIN = new byte[4];
                            byte[] pucSN = new byte[8];
                            IDCardData cardMsg = new IDCardData();
                            nRet = Syn_StartFindIDCard(nPort, ref pucIIN[0], 0); //找卡
                            nRet = Syn_SelectIDCard(nPort, ref pucSN[0], 0); //选卡
                            string cardStr = new string(' ', 256); //身份证基本信息返回长度为256
                            string imgMsg = new string(' ', 1024); //身份证图片信息返回长度为1024
                            IntPtr msg = Marshal.StringToHGlobalAnsi(cardStr); //身份证基本信息
                            IntPtr img = Marshal.StringToHGlobalAnsi(imgMsg); //身份证图片
                            uint mLen = 0;
                            uint iLen = 0;
                            nRet = Syn_ReadBaseMsg(nPort, msg, ref mLen, img, ref iLen, 0);
                            if (nRet == 0)
                            {
                                Syn_ClosePort(nPort);
                                string card = Marshal.PtrToStringUni(msg);
                                char[] cartb = card.ToCharArray();
                                cardMsg.Name = (new string(cartb, 0, 15)).Trim();
                                cardMsg.Sex = new string(cartb, 15, 1);
                                cardMsg.Nation = new string(cartb, 16, 2);
                                cardMsg.Born = new string(cartb, 18, 8);
                                cardMsg.Address = (new string(cartb, 26, 35)).Trim();
                                cardMsg.IDCardNo = new string(cartb, 61, 18);
                                cardMsg.GrantDept = (new string(cartb, 79, 15)).Trim();
                                cardMsg.UserLifeBegin = new string(cartb, 94, 8);
                                cardMsg.UserLifeEnd = new string(cartb, 102, 8);
                                byte[] data=new byte[iLen];
                                Marshal.Copy(img,data,0,data.Length);
                                cardMsg.PhotoBase64Str = GetImageBase64Str(data, cardMsg.IDCardNo);
                                idCardData = cardMsg;
                                status = 0;
                            }
                        }
                        Syn_ClosePort(nPort);
                    }
                }
                else
                {
                    status = 2;
                    //通知界面找不到读卡器
                }
            }
            catch (Exception e)
            {
                status = 3;
            }
            return status;
        }

        private static string GetImageBase64Str(byte[] data, string idCardNo)
        {
            if (!CheckLicense()) return string.Empty;//license.dat文件失败，那么就不能去获取文件
            var wltFileName = Path.Combine(_imageDirPath,
                string.Format("{0}.wlt", idCardNo));
            if (File.Exists(wltFileName))
            {
                File.Delete(wltFileName);
            }
            using (FileStream fs = new FileStream(wltFileName, FileMode.Create))
            {
                fs.Write(data, 0, data.Length);
                fs.Close();
            }
            var nRet = GetBmp(wltFileName, 2);
            if (nRet == 1)
            {
              //  Thread.Sleep(200);
                string bmpFileName = Path.Combine(_imageDirPath,
                    string.Format("{0}.bmp", idCardNo));
                if (File.Exists(bmpFileName))
                {
                    var str = GetFileBase64Str(bmpFileName);
                   // File.Delete(bmpFileName);
                    return str;
                }
            }
            return string.Empty;
        }

        private static string GetFileBase64Str(string fileName)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (Bitmap bmp = new Bitmap(fileName))
                {
                    bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                }
                byte[] arr1 = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr1, 0, (int) ms.Length);
                return Convert.ToBase64String(arr1);
            }
        }
        //检测授权文件
        private static bool CheckLicense()
        {
            var licenceFile = @"c:\license.dat";
            var localFile = @"idCardDll\license.dat";
            try
            {
                if (!File.Exists(licenceFile))
                {
                    //不存在，拷贝文件过去
                    File.Copy(localFile,licenceFile,true);
                    return true;
                }
                //文件存在，需要判断数据是否一致
                string local = string.Empty;
                string license = string.Empty;
                using (FileStream fs = new FileStream(localFile, FileMode.Open, FileAccess.Read))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        local = sr.ReadToEnd();
                    }
                }
                using (FileStream fs = new FileStream(licenceFile, FileMode.Open, FileAccess.Read))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        license = sr.ReadToEnd();
                    }
                }
                if (local == license)
                {
                    return true;
                }
                else
                {
                    File.Copy(localFile, licenceFile, true);
                    return true;
                }
            }
            catch (Exception ex)
            {
                //"判断license失败，不能去获取图片";
                return false;
            }

        }

        public static string GetImgPath(string idCardNo)
        {
            return Path.Combine(_imageDirPath, string.Format("{0}.bmp", idCardNo));
        }
        /// <summary>
        /// 获取状态信息
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        public static string GetStatusMsg(int status)
        {
            string str = null;
            switch (status)
            {
                case 0:
                    str = "读取成功";
                    break;
                case 1:
                    str = "找不到身份证";
                    break;
                case 2:
                    str = "找不到读卡器";
                    break;
                case 3:
                    default:
                    str = "读取失败";
                    break;
            }
            return str;
        }
    }

 
}